﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Media;
using System.Reflection;
using CommonBehaviors.Actions;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Inventory;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;
using System.ComponentModel;

namespace TuanHA_Combat_Routine
{
    public partial class Classname
    {
        #region Attackable

        private static bool Attackable(WoWUnit target, int range)
        {
          return (((BasicCheck(target) && !Blacklist.Contains(target.Guid, BlacklistFlags.All)) && ((GetDistance(target) <= range) && !Invulnerable(target))) && ((!DebuffCCBreakonDamage(target) && IsEnemy(target)) && (((range <= 5) || (GetDistance(target) <= 5f)) || InLineOfSpellSightCheck(target))));        }

        private static bool AttackableNoCC(WoWUnit target, int range)
        {
            return (((BasicCheck(target) && !Blacklist.Contains(target.Guid, BlacklistFlags.Pull | BlacklistFlags.Interact | BlacklistFlags.Node | BlacklistFlags.Combat | BlacklistFlags.Loot)) && ((GetDistance(target) <= range) && !Invulnerable(target))) && (IsEnemy(target) && (((range <= 5) || (GetDistance(target) <= 5f)) || InLineOfSpellSightCheck(target))));
        }

        private static bool AttackableNoCCLoS(WoWUnit target, int range)
        {
            return ((BasicCheck(target) && !Blacklist.Contains(target.Guid, BlacklistFlags.Pull | BlacklistFlags.Interact | BlacklistFlags.Node | BlacklistFlags.Combat | BlacklistFlags.Loot)) && (((GetDistance(target) <= range) && !Invulnerable(target)) && IsEnemy(target)));
        }

        private static bool AttackableNoLoS(WoWUnit target, int range)
        {
            return (((BasicCheck(target) && !Blacklist.Contains(target.Guid, BlacklistFlags.Pull | BlacklistFlags.Interact | BlacklistFlags.Node | BlacklistFlags.Combat | BlacklistFlags.Loot)) && ((GetDistance(target) <= range) && !Invulnerable(target))) && (!DebuffCCBreakonDamage(target) && IsEnemy(target)));
        }

        #endregion

        #region AuraCheck

        private class AuraCacheClass
        {
            internal WoWAura AuraCacheAura { get; set; }

            internal DateTime AuraCacheExpireTime { get; set; }

            internal int AuraCacheId { get; set; }

            internal string AuraCacheName { get; set; }

            internal ulong AuraCacheUnit { get; set; }
        }

        private static readonly List<AuraCacheClass> AuraCacheList = new List<AuraCacheClass>();

        private static void AuraCacheUpdate(WoWUnit target, bool ForceUpdate = false)
        {
            Predicate<AuraCacheClass> match = null;
            Predicate<AuraCacheClass> predicate2 = null;
            AuraCacheClass AuraCacheUnit = AuraCacheList.FirstOrDefault<AuraCacheClass>(unit => unit.AuraCacheUnit == target.Guid);
            if (ForceUpdate)
            {
                if (AuraCacheUnit != null)
                {
                    if (match == null)
                    {
                        match = unit => AuraCacheUnit.AuraCacheUnit == target.Guid;
                    }
                    AuraCacheList.RemoveAll(match);
                }
                DateTime time = DateTime.Now + AuraCacheExpire;
                foreach (WoWAura aura in target.GetAllAuras())
                {
                    AuraCacheClass item = new AuraCacheClass
                    {
                        AuraCacheExpireTime = time,
                        AuraCacheUnit = target.Guid,
                        AuraCacheAura = aura,
                        AuraCacheName = aura.Name,
                        AuraCacheId = aura.SpellId
                    };
                    AuraCacheList.Add(item);

                }
            }
            if (AuraCacheUnit == null)
            {
                DateTime time2 = DateTime.Now + AuraCacheExpire;
                foreach (WoWAura aura2 in target.GetAllAuras())
                {
                    AuraCacheClass class3 = new AuraCacheClass
                    {
                        AuraCacheExpireTime = time2,
                        AuraCacheUnit = target.Guid,
                        AuraCacheAura = aura2,
                        AuraCacheName = aura2.Name,
                        AuraCacheId = aura2.SpellId
                    };
                    AuraCacheList.Add(class3);
                }
            }
            else if (AuraCacheUnit.AuraCacheExpireTime < DateTime.Now)
            {
                if (predicate2 == null)
                {
                    predicate2 = unit => AuraCacheUnit.AuraCacheUnit == target.Guid;
                }
                AuraCacheList.RemoveAll(predicate2);
                DateTime time3 = DateTime.Now + AuraCacheExpire;
                foreach (WoWAura aura3 in target.GetAllAuras())
                {
                    AuraCacheClass class4 = new AuraCacheClass
                    {
                        AuraCacheExpireTime = time3,
                        AuraCacheUnit = target.Guid,
                        AuraCacheAura = aura3,
                        AuraCacheName = aura3.Name,
                        AuraCacheId = aura3.SpellId
                    };
                    AuraCacheList.Add(class4);
                }
            }
        }

        private static bool UnitHasAura(string auraName, WoWUnit target)
        {
            AuraCacheUpdate(target);

            //Logging.Write("========================");
            //Logging.Write("Total AuraCacheAura of {0}", Me.SafeName);
            //foreach (var Aura in AuraCacheList.Where(aura => aura.AuraCacheUnit == Me))
            //{
            //    Logging.Write("Aura.AuraCacheUnit {0} - Aura.AuraCacheAura.Name {1} - Aura.AuraCacheId {2}",
            //                  Aura.AuraCacheUnit, Aura.AuraCacheAura.Name, Aura.AuraCacheId);
            //}

            return AuraCacheList != null &&
                   AuraCacheList.Any(aura => aura.AuraCacheUnit == target.Guid &&
                                             aura.AuraCacheAura.Name == auraName);
        }

        private static bool UnitHasAura(int auraID, WoWUnit target)
        {
            AuraCacheUpdate(target);

            //Logging.Write("========================");
            //Logging.Write("Total AuraCacheAura of {0}", Me.SafeName);
            //foreach (var Aura in AuraCacheList.Where(aura => aura.AuraCacheUnit == Me))
            //{
            //    Logging.Write("Aura.AuraCacheUnit {0} - Aura.AuraCacheAura.Name {1} - Aura.AuraCacheId {2}",
            //                  Aura.AuraCacheUnit, Aura.AuraCacheAura.Name, Aura.AuraCacheId);
            //}


            return AuraCacheList != null &&
                   AuraCacheList.Any(aura => aura.AuraCacheUnit == target.Guid &&
                                             aura.AuraCacheId == auraID);
        }

        private static bool MeHasAura(string auraName)
        {
            AuraCacheUpdate(Me);

            //Logging.Write("========================");
            //Logging.Write("Total AuraCacheAura of {0}", Me.SafeName);
            //foreach (var Aura in AuraCacheList.Where(aura => aura.AuraCacheUnit == Me))
            //{
            //    Logging.Write("Aura.AuraCacheUnit {0} - Aura.AuraCacheAura.Name {1} - Aura.AuraCacheId {2}",
            //                  Aura.AuraCacheUnit, Aura.AuraCacheAura.Name, Aura.AuraCacheId);
            //}

            return AuraCacheList != null &&
                   AuraCacheList.Any(aura => aura.AuraCacheUnit == Me.Guid &&
                                             aura.AuraCacheAura.Name == auraName);
        }

        private static bool MeHasAura(int auraID)
        {
            AuraCacheUpdate(Me);

            //Logging.Write("========================");
            //Logging.Write("Total AuraCacheAura of {0}", Me.SafeName);
            //foreach (var Aura in AuraCacheList.Where(aura => aura.AuraCacheUnit == Me))
            //{
            //    Logging.Write("Aura.AuraCacheUnit {0} - Aura.AuraCacheAura.Name {1} - Aura.AuraCacheId {2}",
            //                  Aura.AuraCacheUnit, Aura.AuraCacheAura.Name, Aura.AuraCacheId);
            //}


            return AuraCacheList != null &&
                   AuraCacheList.Any(aura => aura.AuraCacheUnit == Me.Guid &&
                                             aura.AuraCacheId == auraID);
        }

        private static bool MyAura(string auraName, WoWUnit target)
        {
            if (!BasicCheck(target))
            {
                return false;
            }

            AuraCacheUpdate(target);

            //Logging.Write("========================");
            //Logging.Write("Total AuraCacheAura of {0}", target.SafeName);

            //foreach (var Aura in AuraCacheList.Where(aura => aura.AuraCacheUnit == target .Guid))
            //{
            //    Logging.Write("Aura.AuraCacheUnit {0} - Aura.AuraCacheAura.Name {1} - Aura.AuraCacheId {2}",
            //                  Aura.AuraCacheUnit, Aura.AuraCacheAura.Name, Aura.AuraCacheId);
            //}


            var AuraFound = AuraCacheList != null &&
                            AuraCacheList.Any(
                                aura => aura.AuraCacheUnit == target.Guid &&
                                        aura.AuraCacheAura.Name == auraName &&
                                        aura.AuraCacheAura.CreatorGuid == Me.Guid);

            return AuraFound;
        }


        private static bool MyAura(int auraID, WoWUnit target)
        {
            if (!BasicCheck(target))
            {
                return false;
            }

            AuraCacheUpdate(target);

            //Logging.Write("========================");
            //Logging.Write("Total AuraCacheAura of {0}", target.SafeName);

            //foreach (var Aura in AuraCacheList.Where(aura => aura.AuraCacheUnit == target .Guid))
            //{
            //    Logging.Write("Aura.AuraCacheUnit {0} - Aura.AuraCacheAura.Name {1} - Aura.AuraCacheId {2}",
            //                  Aura.AuraCacheUnit, Aura.AuraCacheAura.Name, Aura.AuraCacheId);
            //}

            var AuraFound = AuraCacheList != null &&
                            AuraCacheList.Any(
                                aura => aura.AuraCacheUnit == target.Guid &&
                                        aura.AuraCacheAura.CreatorGuid == Me.Guid &&
                                        aura.AuraCacheId == auraID);

            return AuraFound;
        }

        private static double MyAuraTimeLeft(string auraName, WoWUnit target)
        {
            if (!BasicCheck(target))
            {
                return 0;
            }

            AuraCacheUpdate(target);

            //Logging.Write("========================");
            //Logging.Write("Total AuraCacheAura of {0}", target.SafeName);

            //foreach (var Aura in AuraCacheList.Where(aura => aura.AuraCacheUnit == target .Guid))
            //{
            //    Logging.Write("Aura.AuraCacheUnit {0} - Aura.AuraCacheAura.Name {1} - Aura.AuraCacheId {2}",
            //                  Aura.AuraCacheUnit, Aura.AuraCacheAura.Name, Aura.AuraCacheId);
            //}

            return AuraCacheList == null
                       ? 0
                       : AuraCacheList.Where(
                           aura =>
                           aura.AuraCacheUnit == target.Guid && aura.AuraCacheAura.CreatorGuid == Me.Guid &&
                           aura.AuraCacheName == auraName)
                                      .Select(Aura => Aura.AuraCacheAura.TimeLeft.TotalMilliseconds)
                                      .FirstOrDefault();

            //if (AuraCacheList != null)
            //{
            //    foreach (var Aura in AuraCacheList)
            //    {
            //        if (Aura.AuraCacheUnit==target&&
            //            Aura.AuraCacheAura.CreatorGuid==Me.Guid&&
            //            Aura.AuraCacheName == auraName)
            //        {
            //            return Aura.AuraCacheAura.TimeLeft.TotalMilliseconds;
            //        }
            //    }
            //}
            //return 0;
        }

        private static double MyAuraTimeLeft(int auraID, WoWUnit target)
        {
            if (!BasicCheck(target))
            {
                return 0;
            }

            AuraCacheUpdate(target);

            //Logging.Write("========================");
            //Logging.Write("Total AuraCacheAura of {0}", target.SafeName);

            //foreach (var Aura in AuraCacheList.Where(aura => aura.AuraCacheUnit == target .Guid))
            //{
            //    Logging.Write("Aura.AuraCacheUnit {0} - Aura.AuraCacheAura.Name {1} - Aura.AuraCacheId {2}",
            //                  Aura.AuraCacheUnit, Aura.AuraCacheAura.Name, Aura.AuraCacheId);
            //}

            return AuraCacheList == null
                       ? 0
                       : AuraCacheList.Where(
                           aura =>
                           aura.AuraCacheUnit == target.Guid && aura.AuraCacheAura.CreatorGuid == Me.Guid &&
                           aura.AuraCacheId == auraID)
                                      .Select(Aura => Aura.AuraCacheAura.TimeLeft.TotalMilliseconds)
                                      .FirstOrDefault();
        }

        private static double MyAuraStackCount(string auraName, WoWUnit target)
        {
            if (!BasicCheck(target))
            {
                return 0;
            }

            AuraCacheUpdate(target);

            //Logging.Write("========================");
            //Logging.Write("Total AuraCacheAura of {0}", target.SafeName);

            //foreach (var Aura in AuraCacheList.Where(aura => aura.AuraCacheUnit == target .Guid))
            //{
            //    Logging.Write("Aura.AuraCacheUnit {0} - Aura.AuraCacheAura.Name {1} - Aura.AuraCacheId {2}",
            //                  Aura.AuraCacheUnit, Aura.AuraCacheAura.Name, Aura.AuraCacheId);
            //}

            return AuraCacheList == null
                       ? 0
                       : AuraCacheList.Where(
                           aura =>
                           aura.AuraCacheUnit == target.Guid && aura.AuraCacheAura.CreatorGuid == Me.Guid &&
                           aura.AuraCacheName == auraName)
                                      .Select(aura => aura.AuraCacheAura.StackCount)
                                      .FirstOrDefault();
        }

        private static double MyAuraStackCount(int auraID, WoWUnit target)
        {
            if (!BasicCheck(target))
            {
                return 0;
            }

            AuraCacheUpdate(target);

            //Logging.Write("========================");
            //Logging.Write("Total AuraCacheAura of {0}", target.SafeName);

            //foreach (var Aura in AuraCacheList.Where(aura => aura.AuraCacheUnit == target .Guid))
            //{
            //    Logging.Write("Aura.AuraCacheUnit {0} - Aura.AuraCacheAura.Name {1} - Aura.AuraCacheId {2}",
            //                  Aura.AuraCacheUnit, Aura.AuraCacheAura.Name, Aura.AuraCacheId);
            //}

            return AuraCacheList == null
                       ? 0
                       : AuraCacheList.Where(
                           aura =>
                           aura.AuraCacheUnit == target.Guid && aura.AuraCacheAura.CreatorGuid == Me.Guid &&
                           aura.AuraCacheId == auraID)
                                      .Select(aura => aura.AuraCacheAura.StackCount)
                                      .FirstOrDefault();
        }

        #endregion

        #region BasicCheck

        private static bool BasicCheck(WoWUnit target)
        {
            return target != null && target.IsValid && target.IsAlive;
        }

        #endregion

        #region  BattleStandard

        private static Composite UseBattleStandard()
        {
            return new Decorator(ret => (((THSettings.Instance.HealthStone && Me.Combat) && ((HealWeight(Me) < THSettings.Instance.HealthStoneHP) && (Me.CurrentTarget != null))) && (Me.CurrentTarget.CurrentHealth > HealWeight(Me))) && InBattleground, new Action(delegate
            {
                if (Me.IsAlliance)
                {
                    WoWItem item = Me.BagItems.FirstOrDefault<WoWItem>(o => o.Entry == 0x48ae);
                    if ((!MeHasAura("Alliance Battle Standard") && (item != null)) && (item.CooldownTimeLeft.TotalMilliseconds <= MyLatency))
                    {
                        item.Use();
                        Logging.Write("Use Battle Standard at " + HealWeight(Me) + "%");
                    }
                }
                if (Me.IsHorde)
                {
                    WoWItem item2 = Me.BagItems.FirstOrDefault<WoWItem>(o => o.Entry == 0x48af);
                    if ((!MeHasAura("Horde Battle Standard") && (item2 != null)) && (item2.CooldownTimeLeft.TotalMilliseconds <= MyLatency))
                    {
                        item2.Use();
                        Logging.Write("Use Battle Standard at " + HealWeight(Me) + "%");
                    }
                }
                return RunStatus.Failure;
            }));
        }


        #endregion

        //#region BasicCheck

        //private static bool BasicCheck(WoWUnit target)
        //{
        //    return (((target != null) && target.IsValid) && target.IsAlive);
        //}

        //#endregion

        #region ChatFilter
        
        //private static void ChatFilter(Chat.ChatSimpleMessageEventArgs e)
        //{
        //    //.if (THSettings.Instance.FlagReturnorPickup && (((Battlegrounds.Current == BattlegroundType.WSG) || (Battlegrounds.Current == BattlegroundType.TP)) || (Battlegrounds.Current == BattlegroundType.EotS)))
        //    if ((((Battlegrounds.Current == BattlegroundType.WSG) || (Battlegrounds.Current == BattlegroundType.TP)) || (Battlegrounds.Current == BattlegroundType.EotS)))
        //    {
        //        if (e.Message.Contains("Flag was dropped by"))
        //        {
        //            SearchFlagTime = DateTime.Now + TimeSpan.FromSeconds(10.0);
        //        }
        //        else if ((SearchFlagTime > DateTime.Now) && e.Message.Contains("Flag was returned to its base by"))
        //        {
        //            SearchFlagTime = DateTime.Now - TimeSpan.FromSeconds(10.0);
        //        }
        //    }
        //}
        #endregion

        #region CanUseDeathRune
        private static bool CanUseDeathRune()
        {
            if ((THSettings.Instance.NecroticStrikeStack && SpellManager.HasSpell("Necrotic Strike")) && ((Me.DeathRuneCount <= THSettings.Instance.NecroticStrikeDeathRuneNumber) && ((UseSpecialization != 2) || (Me.DeathRuneCount < 2))))
            {
                return false;
            }
            return true;
        }
        #endregion

        #region CanUseEquippedItem

        //Thank Apoc
        private static bool CanUseEquippedItem(WoWItem item)
        {
            if (string.IsNullOrEmpty(Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0)))
            {
                return false;
            }
            return (item.Usable && (item.Cooldown <= 0f));
        }

        #endregion

        #region CastSpell

        private static DateTime LastCastTime = DateTime.Now;
        private static string LastCastSpell;
        private static WoWUnit LastCastUnit;
        //private static string CastReason;
        private static DateTime LastWriteLog;
        private static Color colorlog;

        private static void CastSpell(string spellName, WoWUnit target, string reason = "")
        {
            SpellManager.Cast(spellName, target);
            LastCastSpell = spellName;
            LastCastUnit = target;
            LastCastTime = DateTime.Now;
            if (LastWriteLog <= DateTime.Now)
            {
                LastWriteLog = DateTime.Now + TimeSpan.FromMilliseconds(MyLatency);
                if (((((spellName == "Mind Freeze") || (spellName == "Strangulate")) || ((spellName == "Asphyxiate") || (spellName == "Incebound Fortitude"))) || (((spellName == "Lichborne") || (spellName == "Death Grip")) || ((spellName == "Pillar of Frost") || (spellName == "Unholy Frenzy")))) || ((((spellName == "Empower Rune Weapon") || (spellName == "Summon Gargoyle")) || ((spellName == "Dark Transformation") || (spellName == "Desecrated Ground"))) || ((spellName == "Anti-Magic Zone") || (spellName == "Anti-Magic Shell"))))
                {
                    colorlog = Colors.GhostWhite;
                }
                else if (target == Me)
                {
                    colorlog = Colors.GreenYellow;
                }
                else if (target == Me.CurrentTarget)
                {
                    colorlog = Colors.Yellow;
                }
                else
                {
                    colorlog = Colors.YellowGreen;
                }
                string str = string.Concat(new object[] { "RP: ", PlayerRunicPower(), " (B:", Me.BloodRuneCount, " D:", Me.DeathRuneCount, " F:", Me.FrostRuneCount, " U:", Me.UnholyRuneCount, ")" });
                Logging.Write(colorlog, string.Concat(new object[] { DateTime.Now.ToString("ss:fff"), " HP: ", Math.Round(HealWeight(Me)), "% ", str, " ", target.SafeName, " ", Math.Round(target.Distance, 2), "y ", Math.Round(target.HealthPercent), "% hp ", spellName, " (", reason, ") " }));
                LastCastSpell = spellName;
            }
        }

        #endregion

        #region CountDebuff

        private static double CountDebuff(WoWUnit u)
        {
            if (((u == null) || !u.IsValid) || !u.IsAlive)
            {
                return 0.0;
            }
            return (double)u.Debuffs.Values.Count<WoWAura>(delegate(WoWAura debuff)
            {
                if ((debuff.Spell.DispelType != WoWDispelType.Magic) && (debuff.Spell.DispelType != WoWDispelType.Poison))
                {
                    return (debuff.Spell.DispelType == WoWDispelType.Disease);
                }
                return true;
            });
        }

        private static double CountDebuffAll(WoWUnit u)
        {
            if (((u != null) && u.IsValid) && u.IsAlive)
            {
                return (double)u.Debuffs.Values.Count<WoWAura>();
            }
            return 0.0;
        }

        private static double CountDebuffMagic(WoWUnit u)
        {
            if (((u == null) || !u.IsValid) || !u.IsAlive)
            {
                return 0.0;
            }
            return (double)u.Debuffs.Values.Count<WoWAura>(debuff => (debuff.Spell.DispelType == WoWDispelType.Magic));
        }

        private static double CountDebuffRootandSnareMechanic(WoWUnit u)
        {
            if (((u == null) || !u.IsValid) || !u.IsAlive)
            {
                return 0.0;
            }
            return (double)u.GetAllAuras().Count<WoWAura>(delegate(WoWAura debuff)
            {
                if (debuff.Spell.Mechanic != WoWSpellMechanic.Snared)
                {
                    return (debuff.Spell.Mechanic == WoWSpellMechanic.Rooted);
                }
                return true;
            });
        }

        #endregion

        #region CountDPSTarget

        private static int CountDPSTarget(WoWUnit target)
        {
            Func<WoWUnit, bool> predicate = null;
            Func<WoWUnit, bool> func2 = null;
            if (InArena || InBattleground)
            {
                if (predicate == null)
                {
                    predicate = delegate(WoWUnit unit)
                    {
                        if (((!BasicCheck(unit) || (unit.CurrentTarget == null)) || (!unit.CurrentTarget.IsValid || (unit.CurrentTarget != target))) || ((((TalentSort(unit) < 2) || (TalentSort(unit) > 3)) || (unit.Location.Distance(target.Location) >= 40f)) && ((TalentSort(unit) != 1) || (unit.Location.Distance(target.Location) >= 15f))))
                        {
                            return false;
                        }
                        return !DebuffCC(unit);
                    };
                }
                return NearbyUnFriendlyPlayers.Count<WoWUnit>(predicate);
            }
            if (func2 == null)
            {
                func2 = unit => ((BasicCheck(unit) && (unit.CurrentTarget != null)) && (unit.CurrentTarget.IsValid && (unit.CurrentTarget == target))) && !DebuffCC(unit);
            }
            return NearbyUnFriendlyUnits.Count<WoWUnit>(func2);
        }

        #endregion

        #region CountMagicDPSTarget

        private static int CountMagicDPSTarget(WoWUnit target)
        {
            Func<WoWUnit, bool> predicate = null;
            Func<WoWUnit, bool> func2 = null;
            if (InArena || InBattleground)
            {
                if (predicate == null)
                {
                    predicate = unit => (((BasicCheck(unit) && (unit.CurrentTarget != null)) && (unit.CurrentTarget.IsValid && (unit.CurrentTarget == target))) && ((TalentSort(unit) == 3) && (unit.Location.Distance(target.Location) < 40f))) && !DebuffCC(unit);
                }
                return NearbyUnFriendlyPlayers.Count<WoWUnit>(predicate);
            }
            if (func2 == null)
            {
                func2 = unit => (((BasicCheck(unit) && (unit.CurrentTarget != null)) && (unit.CurrentTarget.IsValid && (unit.CurrentTarget == target))) && ((unit.PowerType == WoWPowerType.Mana) && (unit.Location.Distance(target.Location) < 40f))) && !DebuffCC(unit);
            }
            return NearbyUnFriendlyUnits.Count<WoWUnit>(func2);
        }

        #endregion

        #region CountMeleeDPSTarget

        private static int CountMeleeDPSTarget(WoWUnit target, double distance)
        {
            Func<WoWUnit, bool> predicate = null;
            Func<WoWUnit, bool> func2 = null;
            if (InArena || InBattleground)
            {
                if (predicate == null)
                {
                    predicate = unit => (((BasicCheck(unit) && (unit.CurrentTarget != null)) && (unit.CurrentTarget.IsValid && (unit.CurrentTarget == target))) && ((TalentSort(unit) == 1) && (unit.Location.Distance(target.Location) <= distance))) && !DebuffCC(unit);
                }
                return NearbyUnFriendlyPlayers.Count<WoWUnit>(predicate);
            }
            if (func2 == null)
            {
                func2 = unit => (((BasicCheck(unit) && (unit.CurrentTarget != null)) && (unit.CurrentTarget.IsValid && (unit.CurrentTarget == target))) && (unit.Location.Distance(target.Location) <= distance)) && !DebuffCC(unit);
            }
            return NearbyUnFriendlyUnits.Count<WoWUnit>(func2);
        }

        #endregion

        #region CountMeleeFriendDPSTarget

        private static int CountMeleeFriendDPSTarget(WoWUnit target, double distance)
        {
            Func<WoWUnit, bool> predicate = null;
            Func<WoWUnit, bool> func2 = null;
            if (InArena || InBattleground)
            {
                if (predicate == null)
                {
                    predicate = unit => (((BasicCheck(unit) && (unit.CurrentTarget != null)) && (unit.CurrentTarget.IsValid && (unit.CurrentTarget == target))) && ((TalentSort(unit) == 1) && (unit.Location.Distance(target.Location) <= distance))) && !DebuffCC(unit);
                }
                return FarFriendlyPlayers.Count<WoWUnit>(predicate);
            }
            if (func2 == null)
            {
                func2 = unit => (((BasicCheck(unit) && (unit.CurrentTarget != null)) && (unit.CurrentTarget.IsValid && (unit.CurrentTarget == target))) && (unit.Location.Distance(target.Location) <= distance)) && !DebuffCC(unit);
            }
            return FarFriendlyPlayers.Count<WoWUnit>(func2);
        }

        #endregion

        #region CountPhysicDPSTarget

        private static int CountPhysicDPSTarget(WoWUnit target)
        {
            Func<WoWUnit, bool> predicate = null;
            Func<WoWUnit, bool> func2 = null;
            if (InArena || InBattleground)
            {
                if (predicate == null)
                {
                    predicate = delegate(WoWUnit unit)
                    {
                        if (((!BasicCheck(unit) || (unit.CurrentTarget == null)) || (!unit.CurrentTarget.IsValid || (unit.CurrentTarget != target))) || (((TalentSort(unit) != 2) || (unit.Location.Distance(target.Location) >= 40f)) && ((TalentSort(unit) != 1) || (unit.Location.Distance(target.Location) >= 25f))))
                        {
                            return false;
                        }
                        return !DebuffCC(unit);
                    };
                }
                return NearbyUnFriendlyPlayers.Count<WoWUnit>(predicate);
            }
            if (func2 == null)
            {
                func2 = unit => (((BasicCheck(unit) && (unit.CurrentTarget != null)) && (unit.CurrentTarget.IsValid && (unit.CurrentTarget == target))) && (unit.Location.Distance(target.Location) < 15f)) && !DebuffCC(unit);
            }
            return NearbyUnFriendlyUnits.Count<WoWUnit>(func2);
        }

        #endregion

        #region CountEnemyNear

        private static double CountEnemyNear(WoWUnit unitCenter, float distance)
        {
            return (double)FarUnFriendlyUnits.Where<WoWUnit>(new Func<WoWUnit, bool>(Classname.BasicCheck)).Count<WoWUnit>(delegate(WoWUnit unit)
            {
                if ((!InProvingGrounds && !IsDummy(unit)) && ((!unit.Combat || (unit.MaxHealth <= (MeMaxHealth * 0.2))) || (!unit.GotTarget || !FarFriendlyUnits.Contains(unit.CurrentTarget))))
                {
                    return false;
                }
                return (GetDistance(unitCenter, unit) <= distance);
            });
        }

        #endregion

        #region CountEnemyNearNoCC

        private static double CountEnemyNearNoCC(WoWUnit unitCenter, float distance)
        {
            return (double)NearbyUnFriendlyUnits.Count<WoWUnit>(delegate(WoWUnit unit)
            {
                if ((!BasicCheck(unit) || (unitCenter.Location.Distance(unit.Location) > distance)) || (unit.IsPet || DebuffCC(unit)))
                {
                    return false;
                }
                return ((InProvingGrounds || IsDummy(unit)) || ((unit.Combat && unit.GotTarget) && FarFriendlyPlayers.Contains(unit.CurrentTarget)));
            });
        }

        #endregion

        #region CountEnemyNearNoCCBreakonDamge

        //private static double CountEnemyNearNoCCBreakonDamge(WoWUnit unitCenter, float distance)
        //{
        //    if (unitCenter == null || !unitCenter.IsValid)
        //    {
        //        return 0;
        //    }
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            unit.IsValid &&
        //            unitCenter.Location.Distance(unit.Location) <= distance &&
        //            DebuffCCBreakonDamage(unit)).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountEnemyDontHaveBloodPlagueorFrostFever

        ////private static double TotalEnemyDontHaveBloodPlagueorFrostFever;

        //private static double CountEnemyDontHaveBloodPlagueorFrostFever()
        //{
        //    //TotalEnemyDontHaveBloodPlagueorFrostFever = 0;
        //    //Logging.Write("Enter CountEnemyDontHaveBloodPlagueorFrostFever:" + TotalEnemyDontHaveBloodPlagueorFrostFever);
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            unit.IsValid &&
        //            !unit.IsPet &&
        //            (IsDummy(unit) ||
        //             unit.Combat &&
        //             (unit.IsTargetingMyPartyMember ||
        //              unit.IsTargetingMyRaidMember ||
        //              unit.IsTargetingMeOrPet)) &&
        //            (MyAuraTimeLeft("Frost Fever", unit) < 3000 ||
        //             MyAuraTimeLeft("Blood Plague", unit) < 3000) &&
        //            Attackable(unit, 10)).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);

        //    //Logging.Write("TotalEnemyDontHaveBloodPlagueorFrostFever: " + TotalEnemyDontHaveBloodPlagueorFrostFever);
        //    //Logging.Write("CountEnemyNear" + CountEnemyNear(Me, 10));
        //    //return TotalEnemyDontHaveBloodPlagueorFrostFever;
        //}

        #endregion

        #region CountEnemyDontHaveFrostFever

        //private static double CountEnemyDontHaveFrostFever()
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            unit.IsValid &&
        //            (unit.Combat || IsDummy(unit)) &&
        //            !unit.IsPet &&
        //            (IsDummy(unit) ||
        //             unit.IsTargetingMyPartyMember ||
        //             unit.IsTargetingMyRaidMember ||
        //             unit.IsTargetingMeOrPet) &&
        //            !MyAura("Frost Fever", unit) &&
        //            Attackable(unit, 10)).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountEnemyHaveFrostFever

        //private static double CountEnemyHaveFrostFever()
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            unit.IsValid &&
        //            (unit.Combat || IsDummy(unit)) &&
        //            (IsDummy(unit) ||
        //             unit.IsTargetingMyPartyMember ||
        //             unit.IsTargetingMyRaidMember ||
        //             unit.IsTargetingMeOrPet) &&
        //            MyAura("Frost Fever", unit) &&
        //            Attackable(unit, 10)).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountEnemyDontHaveBloodPlague

        //private static double CountEnemyDontHaveBloodPlague()
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            unit.IsValid &&
        //            (unit.Combat || IsDummy(unit)) &&
        //            (IsDummy(unit) ||
        //             unit.IsTargetingMyPartyMember ||
        //             unit.IsTargetingMyRaidMember ||
        //             unit.IsTargetingMeOrPet) &&
        //            !MyAura("Blood Plague", unit) &&
        //            Attackable(unit, 10)).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountEnemyHaveBloodPlague

        //private static double CountEnemyHaveBloodPlague()
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            unit.IsValid &&
        //            (unit.Combat || IsDummy(unit)) &&
        //            !unit.IsPet &&
        //            (IsDummy(unit) ||
        //             unit.IsTargetingMyPartyMember ||
        //             unit.IsTargetingMyRaidMember ||
        //             unit.IsTargetingMeOrPet) &&
        //            MyAura("Blood Plague", unit) &&
        //            Attackable(unit, 10)).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountEnemyFromPoint

        //private static double CountEnemyFromPoint(WoWPoint pointCenter, float radius)
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            pointCenter.Distance(unit.Location) <= radius &&
        //            unit.Combat).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountEneyTargettingUnit

        private static double CountEneyTargettingUnit(WoWUnit target, float distance)
        {
            return (from unit in NearbyUnFriendlyUnits
                    where (((BasicCheck(unit) && (unit.Distance < distance)) && ((unit.CurrentTarget != null) && unit.CurrentTarget.IsValid)) && ((unit.Level <= (target.Level + 3)) && !unit.IsPet)) && (unit.CurrentTarget == target)
                    select unit).Aggregate<WoWUnit, double>(0.0, (current, unit) => (current + 1.0));
        }

        #endregion

        #region CurrentTargetCheck

        private static WoWUnit CurrentTargetCheckLast;
        private static double CurrentTargetCheckDist;
        //private static bool CurrentTargetCheckIsWithinMeleeRange;
        private static bool CurrentTargetCheckDebuffCCBreakonDamage;
        private static bool CurrentTargetCheckInvulnerable;
        //private static bool CurrentTargetCheckInvulnerableePhysic;
        private static bool CurrentTargetCheckIsEnemy;
        private static bool CurrentTargetCheckInLineOfSpellSight;
        private static bool CurrentTargetCheckFacing;
        private static DateTime CurrentTargetCheckLastTime;
        private static bool CurrentTargetCheckInvulnerableMagic;
        private static bool CurrentTargetCheckInvulnerablePhysic;

        private static void CurrentTargetCheck()
        {
            if (CurrentTargetCheckLastTime <= DateTime.Now)
            {
                CurrentTargetCheckLastTime = DateTime.Now + CurrentTargetCheckTimeOut;
                if (BasicCheck(Me.CurrentTarget))
                {
                    CurrentTargetCheckLast = Me.CurrentTarget;
                    CurrentTargetCheckFacing = Me.IsSafelyFacing(Me.CurrentTarget, 180f);
                    CurrentTargetCheckDist = GetDistance(Me.CurrentTarget);
                    CurrentTargetCheckIsEnemy = IsEnemy(Me.CurrentTarget);
                    if (CurrentTargetCheckIsEnemy)
                    {
                        CurrentTargetCheckInvulnerable = Invulnerable(Me.CurrentTarget);
                        if (!CurrentTargetCheckInvulnerable)
                        {
                            CurrentTargetCheckDebuffCCBreakonDamage = DebuffCCBreakonDamage(Me.CurrentTarget);
                            if (!CurrentTargetCheckDebuffCCBreakonDamage)
                            {
                                CurrentTargetCheckInvulnerableMagic = InvulnerableSpell(Me.CurrentTarget);
                                CurrentTargetCheckInvulnerablePhysic = InvulnerablePhysic(Me.CurrentTarget);
                                if (CurrentTargetCheckDist <= 5.0)
                                {
                                    CurrentTargetCheckInLineOfSpellSight = true;
                                }
                                else if (InLineOfSpellSightCheck(Me.CurrentTarget))
                                {
                                    CurrentTargetCheckInLineOfSpellSight = true;
                                }
                            }
                        }
                    }
                }
            }
        }

        private static bool CurrentTargetAttackable(double distance, bool includeCurrentTargetCheckInvulnerableePhysic = false, bool includeCurrentTargetCheckInvulnerableeMagic = false)
        {
            if (((Me.CurrentTarget == null) || !Me.CurrentTarget.IsValid) || (!Me.CurrentTarget.Attackable || !Me.CurrentTarget.IsAlive))
            {
                return false;
            }
            if (Me.CurrentTarget != CurrentTargetCheckLast)
            {
                CurrentTargetCheck();
            }
            return (((((CurrentTargetCheckIsEnemy && !CurrentTargetCheckDebuffCCBreakonDamage) && !CurrentTargetCheckInvulnerable) && ((CurrentTargetCheckFacing || THSettings.Instance.AutoFace) || !IsOverrideModeOn)) && (!includeCurrentTargetCheckInvulnerableePhysic || !CurrentTargetCheckInvulnerablePhysic)) && ((!includeCurrentTargetCheckInvulnerableeMagic || !CurrentTargetCheckInvulnerableMagic) && ((CurrentTargetCheckDist <= distance) && CurrentTargetCheckInLineOfSpellSight)));
        }


        private static bool CurrentTargetAttackableNoLoS(double distance)
        {
            if (((Me.CurrentTarget == null) || !Me.CurrentTarget.IsValid) || (!Me.CurrentTarget.Attackable || !Me.CurrentTarget.IsAlive))
            {
                return false;
            }
            if (Me.CurrentTarget != CurrentTargetCheckLast)
            {
                CurrentTargetCheck();
            }
            return ((!CurrentTargetCheckDebuffCCBreakonDamage && !CurrentTargetCheckInvulnerable) && (CurrentTargetCheckIsEnemy && (CurrentTargetCheckDist <= distance)));
        }

        #endregion

        #region FacingOverride

        private static bool FacingOverride(WoWUnit unit)
        {
            if (!BasicCheck(unit))
            {
                return false;
            }
            if (!Me.IsSafelyFacing(unit, 180f) && (!THSettings.Instance.AutoFace || IsOverrideModeOn))
            {
                return false;
            }
            return true;
        }

        #endregion

        #region GCD

        private static bool GCDL()
        {
            TimeSpan span = (TimeSpan)(DateTime.Now - LastCastTime);
            return ((span.TotalMilliseconds < MyLatency) && (SpellManager.GlobalCooldownLeft.TotalMilliseconds > MyLatency));
        }

        private static bool Casting()
        {
            return (Me.IsCasting || Me.IsChanneling);
        }


        private static bool CastingorGCDL()
        {
            if (!Casting())
            {
                return GCDL();
            }
            return true;
        }

        #endregion

        #region GetAsyncKeyState

        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        #endregion

        #region GetCurrentSpec

        internal static string GetCurrentSpec()
        {
            if (Me.Specialization == WoWSpec.DeathKnightFrost)
            {
                return "Frost";
            }
            if (Me.Specialization == WoWSpec.DeathKnightBlood)
            {
                return "Blood";
            }
            if (Me.Specialization == WoWSpec.DeathKnightUnholy)
            {
                return "Unholy";
            }
            Logging.Write("No Specialization detected");
            return "No Specialization detected";
        }

        #endregion

        #region GetSpellCooldown

        private static TimeSpan GetSpellCooldown(int spell)
        {
            SpellFindResults results;
            if (!SpellManager.FindSpell(spell, out results))
            {
                return TimeSpan.MaxValue;
            }
            if (results.Override == null)
            {
                return results.Original.CooldownTimeLeft;
            }
            return results.Override.CooldownTimeLeft;
        }

        private static TimeSpan GetSpellCooldown(string spell)
        {
            SpellFindResults results;
            if (!SpellManager.FindSpell(spell, out results))
            {
                return TimeSpan.FromMilliseconds(0.0);
            }
            if (results.Override != null)
            {
                return results.Override.CooldownTimeLeft;
            }
            return results.Original.CooldownTimeLeft;
        }

        #endregion

        #region GetRuneSlot
        private static int BloodRuneSlot;
        private static int FrostRuneSlot;
        private static int UnholyRuneSlot;

        private static bool GetRuneSlot()
        {
            BloodRuneSlot = 0;
            DeathRuneSlot = 0;
            FrostRuneSlot = 0;
            UnholyRuneSlot = 0;
            for (int i = 0; i < 6; i++)
            {
                string str2 = Me.GetRuneType(i).ToString();
                if (str2 != null)
                {
                    if (!(str2 == "Blood"))
                    {
                        if (str2 == "Death")
                        {
                            goto Label_007E;
                        }
                        if (str2 == "Frost")
                        {
                            goto Label_008C;
                        }
                        if (str2 == "Unholy")
                        {
                            goto Label_009A;
                        }
                    }
                    else
                    {
                        BloodRuneSlot++;
                    }
                }
                continue;
            Label_007E:
                DeathRuneSlot++;
                continue;
            Label_008C:
                FrostRuneSlot++;
                continue;
            Label_009A:
                UnholyRuneSlot++;
            }
            return true;
        }
        #endregion

        #region GetUnitAuras

        #endregion

        #region GetDistance

        private static float GetDistance(WoWUnit target)
        {
            if ((target == null) || !target.IsValid)
            {
                return 10000f;
            }
            if (target.CombatReach < 3f)
            {
                return (float)target.Distance;
            }
            return ((((float)target.Distance) - target.CombatReach) + 1f);
        }

        private static float GetDistance(WoWUnit source, WoWUnit target)
        {
            if (source == null ||
                !source.IsValid ||
                target == null ||
                !target.IsValid)
            {
                return 10000;
            }

            if (target.CombatReach < 3)
            {
                return source.Location.Distance(target.Location);
            }

            return source.Location.Distance(target.Location) - target.CombatReach + 1;
        }

        #endregion

        #region GetUnitAttckingMyMinion

        //private static WoWUnit UnitAttckingMyMinion;

        //private static bool GetUnitAttckingMyMinion()
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        UnitAttckingMyMinion = null;

        //        UnitAttckingMyMinion = NearbyUnFriendlyUnits.FirstOrDefault(
        //            unit =>
        //            unit != null &&
        //            unit.IsValid &&
        //            unit.Combat &&
        //            unit.CurrentTarget != null &&
        //            unit.CurrentTarget.IsValid &&
        //            unit.CurrentTarget.CreatedByUnitGuid == Me.Guid
        //            );

        //        return UnitAttckingMyMinion != null;
        //    }
        //}

        #endregion

        #region GetBestTarget

        private static WoWUnit UnitBestTarget;

        private static bool GetBestTarget()
        {
            UnitBestTarget = null;
            if (InBattleground || InArena)
            {
                if (DebuffRootorSnare(Me))
                {
                    UnitBestTarget = (from unit in NearbyUnFriendlyPlayers.Where<WoWUnit>(new Func<WoWUnit, bool>(Classname.BasicCheck))
                                      orderby unit.CurrentHealth
                                      select unit).FirstOrDefault<WoWUnit>(unit => Attackable(unit, 5));
                }
                else
                {
                    UnitBestTarget = (from unit in NearbyUnFriendlyPlayers.Where<WoWUnit>(new Func<WoWUnit, bool>(Classname.BasicCheck))
                                      orderby unit.CurrentHealth
                                      select unit).FirstOrDefault<WoWUnit>(unit => Attackable(unit, 20));
                }
                if (UnitBestTarget == null)
                {
                    UnitBestTarget = (from unit in NearbyUnFriendlyPlayers.Where<WoWUnit>(new Func<WoWUnit, bool>(Classname.BasicCheck))
                                      orderby unit.Distance
                                      select unit).FirstOrDefault<WoWUnit>(unit => Attackable(unit, 60));
                }
            }
            if (UnitBestTarget == null)
            {
                UnitBestTarget = (from unit in FarUnFriendlyUnits.Where<WoWUnit>(new Func<WoWUnit, bool>(Classname.BasicCheck))
                                  orderby unit.CurrentHealth
                                  select unit).FirstOrDefault<WoWUnit>(delegate(WoWUnit unit)
                {
                    if (!InProvingGrounds && (!unit.GotTarget || !IsMyPartyRaidMember(unit.CurrentTarget)))
                    {
                        return false;
                    }
                    return Attackable(unit, 5);
                });
            }
            if (UnitBestTarget == null)
            {
                UnitBestTarget = (from unit in FarUnFriendlyUnits.Where<WoWUnit>(new Func<WoWUnit, bool>(Classname.BasicCheck))
                                  orderby unit.CurrentHealth
                                  select unit).FirstOrDefault<WoWUnit>(delegate(WoWUnit unit)
                {
                    if (!InProvingGrounds && (!unit.GotTarget || !IsMyPartyRaidMember(unit.CurrentTarget)))
                    {
                        return false;
                    }
                    return Attackable(unit, 20);
                });
            }
            if (UnitBestTarget == null)
            {
                UnitBestTarget = (from unit in FarUnFriendlyUnits.Where<WoWUnit>(new Func<WoWUnit, bool>(Classname.BasicCheck))
                                  orderby unit.CurrentHealth
                                  select unit).FirstOrDefault<WoWUnit>(delegate(WoWUnit unit)
                {
                    if (!InProvingGrounds && (!unit.GotTarget || !IsMyPartyRaidMember(unit.CurrentTarget)))
                    {
                        return false;
                    }
                    return Attackable(unit, 40);
                });
            }
            return BasicCheck(UnitBestTarget);
        }

        #endregion

        #region GetUnitLowThreat

        //private static WoWUnit UnitLowThreat;

        //private static bool GetUnitLowThreat()
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        UnitLowThreat = null;

        //        UnitLowThreat = NearbyUnFriendlyUnits.OrderBy(unit => unit.ThreatInfo.RawPercent).FirstOrDefault(
        //            unit => unit != null && unit.IsValid &&
        //                    Me.Combat &&
        //                    FacingOverride(unit) &&
        //                    (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
        //                     unit.IsTargetingMeOrPet) &&
        //                    Attackable(unit, 5));
        //        return UnitLowThreat != null;
        //    }
        //}

        #endregion

        #region GetSpellPowerCost
        private static double GetSpellPowerCost(int spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                return ((results.Override != null) ? ((double)results.Override.PowerCost) : ((double)results.Original.PowerCost));
            }
            return 99999.9;
        }

        private static double GetSpellPowerCost(string spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                return ((results.Override != null) ? ((double)results.Override.PowerCost) : ((double)results.Original.PowerCost));
            }
            return 99999.9;
        }
        #endregion

        #region GlobalCheck

        private static bool HasAuraPreparation;
        private static bool HasAuraArenaPreparation;

        private static bool InArena;
        private static bool InBattleground;
        //private static bool InInstance;
        private static bool InDungeon;
        private static bool InRaid;
        private static bool InProvingGrounds;
        private static DateTime GlobalCheckTime;
        private static TimeSpan AuraCacheExpire;
        private static TimeSpan CurrentTargetCheckTimeOut;


        private static void GlobalCheck()
        {
            if (GlobalCheckTime <= DateTime.Now)
            {
                GlobalCheckTime = DateTime.Now + TimeSpan.FromSeconds(30.0);
                HasAuraPreparation = Me.HasAura("Preparation");
                HasAuraArenaPreparation = Me.HasAura("Arena Preparation");
                InArena = Me.CurrentMap.IsArena;
                InBattleground = Me.CurrentMap.IsBattleground;
                InProvingGrounds = Me.CurrentMap.Name == "Proving Grounds";
                InDungeon = Me.CurrentMap.IsDungeon;
                InRaid = Me.CurrentMap.IsRaid;
                UpdateMyLatency();
                UpdateEventHandler();
                if (InRaid)
                {
                    AuraCacheExpire = TimeSpan.FromMilliseconds(500.0);
                    CurrentTargetCheckTimeOut = TimeSpan.FromMilliseconds(500.0);
                }
                else if (InArena || InBattleground)
                {
                    AuraCacheExpire = TimeSpan.FromMilliseconds(0);
                    CurrentTargetCheckTimeOut = TimeSpan.FromMilliseconds(0);
                }
                else
                {
                    AuraCacheExpire = TimeSpan.FromMilliseconds(100.0);
                    CurrentTargetCheckTimeOut = TimeSpan.FromMilliseconds(100.0);
                }
            }
        }

        #endregion

        #region HasHealerWithMe
        private static bool HasHealerWithMe()
        {
            if (InArena)
            {
                return FarFriendlyPlayers.Any<WoWUnit>(unit => BasicCheck(unit) && TalentSort(unit) == 4 && !DebuffCC(unit) && !DebuffSilence(unit) && (!DebuffRoot(unit) || InLineOfSpellSightCheck(unit)) && unit.Location.Distance(Me.Location) <= 50);
            }
            else if (InBattleground)
            {
                return FarFriendlyPlayers.Any<WoWUnit>(unit => BasicCheck(unit) && TalentSort(unit) == 4 && unit.CurrentTarget == Me && !DebuffCC(unit) && !DebuffSilence(unit) && (!DebuffRoot(unit) || InLineOfSpellSightCheck(unit)) && unit.Location.Distance(Me.Location) <= 40);
            }
            return FarFriendlyPlayers.Any<WoWUnit>(unit => BasicCheck(unit) && TalentSort(unit) == 4 && !DebuffCC(unit) && !DebuffSilence(unit) && (!DebuffRoot(unit) || InLineOfSpellSightCheck(unit)) && unit.Location.Distance(Me.Location) <= 50);
        }
        #endregion
        
        #region HasMeleeFriendDPSTarget
        private static bool HasMeleeFriendDPSTarget(WoWUnit target, double distance)
        {
            Func<WoWUnit, bool> predicate = null;
            if (!InArena && !InBattleground)
            {
                return FarFriendlyPlayers.Any<WoWUnit>(unit => ((((BasicCheck(unit) && (unit.CurrentTarget != null)) && (unit.CurrentTarget.IsValid && (unit.CurrentTarget == target))) && (unit.Location.Distance(target.Location) <= distance)) && !DebuffCC(unit)));
            }
            if (predicate == null)
            {
                predicate = unit => (((BasicCheck(unit) && (unit.CurrentTarget != null)) && (unit.CurrentTarget.IsValid && (unit.CurrentTarget == target))) && ((TalentSort(unit) == 1) && (unit.Location.Distance(target.Location) <= distance))) && !DebuffCC(unit);
            }
            return FarFriendlyPlayers.Any<WoWUnit>(predicate);
        }

        #endregion

        #region HasEnemyNearGotCCBreakonDamge
        private static bool HasEnemyNearGotCCBreakonDamge(WoWUnit unitCenter, float distance)
        {
            if (!InArena && !InBattleground)
            {
                return false;
            }
            return FarUnFriendlyPlayers.Where<WoWUnit>(new Func<WoWUnit, bool>(Classname.BasicCheck)).Any<WoWUnit>(unit => ((((unit.MaxHealth > (MeMaxHealth * 0.3)) && ((InProvingGrounds || IsDummy(unit)) || (unit.Combat && FarFriendlyPlayers.Contains(unit.CurrentTarget)))) && (GetDistance(unitCenter, unit) <= distance)) && DebuffCCBreakonDamage(unit)));
        }
        #endregion

        #region HasEnemyDontHaveBloodPlague
        private static bool HasEnemyDontHaveBloodPlague()
        {
            return NearbyUnFriendlyUnits.Any<WoWUnit>(unit => ((((BasicCheck(unit) && !unit.IsPet) && ((InProvingGrounds || IsDummy(unit)) || ((unit.Combat && unit.GotTarget) && FarFriendlyPlayers.Contains(unit.CurrentTarget)))) && !MyAura("Blood Plague", unit)) && Attackable(unit, 10 + GlyphprivateofPestilenceBonus)));
        }

        private static bool HasEnemyDontHaveBloodPlagueorFrostFever()
        {
            return NearbyUnFriendlyUnits.Any<WoWUnit>(delegate(WoWUnit unit)
            {
                if ((!BasicCheck(unit) || unit.IsPet) || (MyAura("Frost Fever", unit) && MyAura("Blood Plague", unit)))
                {
                    return false;
                }
                return Attackable(unit, 10 + GlyphprivateofPestilenceBonus);
            });
        }
        #endregion

        #region HasEnemyDontHaveFrostFever
        private static bool HasEnemyDontHaveFrostFever()
        {
            return NearbyUnFriendlyUnits.Any<WoWUnit>(unit => ((((BasicCheck(unit) && !unit.IsPet) && ((InProvingGrounds || IsDummy(unit)) || ((unit.Combat && unit.GotTarget) && FarFriendlyPlayers.Contains(unit.CurrentTarget)))) && !MyAura("Frost Fever", unit)) && Attackable(unit, 10)));
        }
        #endregion

        #region HasEnemyHaveBloodPlague
        private static bool HasEnemyHaveBloodPlague()
        {
            return NearbyUnFriendlyUnits.Any<WoWUnit>(unit => ((((BasicCheck(unit) && !unit.IsPet) && ((InProvingGrounds || IsDummy(unit)) || ((unit.Combat && unit.GotTarget) && FarFriendlyPlayers.Contains(unit.CurrentTarget)))) && MyAura("Blood Plague", unit)) && Attackable(unit, 10)));
        }
        #endregion

        #region HasEnemyHaveFrostFever
        private static bool HasEnemyHaveFrostFever()
        {
            return NearbyUnFriendlyUnits.Any<WoWUnit>(unit => ((((BasicCheck(unit) && !unit.IsPet) && ((InProvingGrounds || IsDummy(unit)) || ((unit.Combat && unit.GotTarget) && FarFriendlyPlayers.Contains(unit.CurrentTarget)))) && MyAura("Frost Fever", unit)) && Attackable(unit, 10 + GlyphprivateofPestilenceBonus)));
        }
        #endregion

        #region HasEnemyNear
        private static bool HasEnemyNear(WoWUnit unitCenter, float distance)
        {
            return FarUnFriendlyUnits.Where<WoWUnit>(new Func<WoWUnit, bool>(Classname.BasicCheck)).Any<WoWUnit>(delegate(WoWUnit unit)
            {
                if ((!InProvingGrounds && !IsDummy(unit)) && ((!unit.Combat || (unit.MaxHealth <= (MeMaxHealth * 0.2))) || (!unit.GotTarget || !FarFriendlyUnits.Contains(unit.CurrentTarget))))
                {
                    return false;
                }
                return (GetDistance(unitCenter, unit) <= distance);
            });
        }
        #endregion

        #region HasMagicBuffDispel
        private static bool HasMagicBuffDispel(WoWUnit target)
        {
            AuraCacheUpdate(target, false);
            return AuraCacheList.Any<AuraCacheClass>(a => ((((a.AuraCacheUnit == target.Guid) && a.AuraCacheAura.IsActive) && !a.AuraCacheAura.IsHarmful) && (a.AuraCacheAura.Spell.DispelType == WoWDispelType.Magic)));
        }
        #endregion

        #region Healable

        private static bool Healable(WoWUnit target, int distance = 40)
        {
            return
                GetDistance(target) <= distance &&
                !IsEnemy(target) &&
                !DebuffDoNotHeal(target) &&
                InLineOfSpellSightCheck(target);
        }

        #endregion

        #region HealWeight

        //////done

        //private static int HealBalancingValue;

        private static double HealWeight(WoWUnit target)
        {
            Func<WoWUnit, bool> predicate = null;
            Func<WoWUnit, bool> func2 = null;
            if (!BasicCheck(target))
            {
                return 1000.0;
            }
            if (!target.Combat)
            {
                return target.HealthPercent;
            }
            int num = 0;
            if (InArena || InBattleground)
            {
                if (predicate == null)
                {
                    predicate = unit => (BasicCheck(unit) && unit.Combat) && (unit.CurrentTarget == target);
                }
                foreach (WoWUnit unit in FarUnFriendlyPlayers.Where<WoWUnit>(predicate))
                {
                    if ((TalentSort(unit) < 4) && BuffBurst(unit))
                    {
                        num += 5;
                    }
                    else
                    {
                        num += 3;
                    }
                }
            }
            else
            {
                if (func2 == null)
                {
                    func2 = unit => (BasicCheck(unit) && unit.Combat) && (unit.CurrentTarget == target);
                }
                foreach (WoWUnit unit2 in FarUnFriendlyUnits.Where<WoWUnit>(func2))
                {
                    if (unit2.IsBoss)
                    {
                        num += 5;
                    }
                    else
                    {
                        num++;
                    }
                }
            }
            //return (target.HealthPercent - num);
            return (target.HealthPercent);
        }

        #endregion

        #region HoldBotAction
        //////done
        private static void HoldBotAction(string spellName)
        {
            if (IsUsingAFKBot)
            {
                new Wait(TimeSpan.FromMilliseconds(3000), ret => Me.IsCasting, new ActionAlwaysSucceed());

                //StyxWoW.SleepForLagDuration();

                while (Me.IsCasting)
                {
                    Logging.Write(LogLevel.Diagnostic, "HoldBotAction Casting " + spellName);
                }

                new WaitContinue(TimeSpan.FromMilliseconds(3000), ret => !Me.IsCasting, new ActionAlwaysSucceed());

                //StyxWoW.SleepForLagDuration();
            }
        }

        #endregion

        #region IndexToKeys

        //private static Keys KeyTwo;

        private static Keys IndexToKeys(int index)
        {
            switch (index)
            {
                case 1:
                    return Keys.A;
                case 2:
                    return Keys.B;
                case 3:
                    return Keys.C;
                case 4:
                    return Keys.D;
                case 5:
                    return Keys.E;
                case 6:
                    return Keys.F;
                case 7:
                    return Keys.G;
                case 8:
                    return Keys.H;
                case 9:
                    return Keys.I;
                case 10:
                    return Keys.J;
                case 11:
                    return Keys.K;
                case 12:
                    return Keys.L;
                case 13:
                    return Keys.M;
                case 14:
                    return Keys.N;
                case 15:
                    return Keys.O;
                case 16:
                    return Keys.P;
                case 17:
                    return Keys.Q;
                case 18:
                    return Keys.R;
                case 19:
                    return Keys.S;
                case 20:
                    return Keys.T;
                case 21:
                    return Keys.U;
                case 22:
                    return Keys.V;
                case 23:
                    return Keys.W;
                case 24:
                    return Keys.X;
                case 25:
                    return Keys.Y;
                case 26:
                    return Keys.Z;
                case 27:
                    return Keys.D1;
                case 28:
                    return Keys.D2;
                case 29:
                    return Keys.D3;
                case 30:
                    return Keys.D4;
                case 31:
                    return Keys.D5;
                case 32:
                    return Keys.D6;
                case 33:
                    return Keys.D7;
                case 34:
                    return Keys.D8;
                case 35:
                    return Keys.D9;
                case 36:
                    return Keys.D0;
                case 37:
                    return Keys.Up;
                case 38:
                    return Keys.Down;
                case 39:
                    return Keys.Left;
                case 40:
                    return Keys.Right;
            }
            return Keys.None;
        }

        internal static Keys IndexToKeysMod(int index)
        {
            switch (index)
            {
                case 1:
                    return Keys.LShiftKey;
                case 2:
                    return Keys.LControlKey;
                case 3:
                    return Keys.Alt;
            }
            return Keys.None;
        }

        #endregion

        #region IsAttacking

        //private static bool IsAttacking()
        //{
        //    return Me.IsCasting && Me.CastingSpell.Name == "Denounce";
        //}

        #endregion

        #region IsDummy

        private static bool IsDummy(WoWUnit target)
        {
            if (!BasicCheck(target))
            {
                return false;
            }
            if (((((target.Entry != 0x79aa) && (target.Entry != 0x10637)) && ((target.Entry != 0xb637) && (target.Entry != 0x7f22))) && (((target.Entry != 0x79a8) && (target.Entry != 0x7f1f)) && ((target.Entry != 0x7f9b) && (target.Entry != 0x7f1e)))) && (target.Entry != 0x7f9a))
            {
                return (target.Entry == 0x773f);
            }
            return true;
        }

        #endregion

        #region IsEnemy

        //private static WoWUnit MyPartyorRaidUnit;

        private static bool IsMyPartyRaidMember(WoWUnit target)
        {
            if (NeedHealUnit(target))
            {
                return true;
            }
            if (target.IsPlayer)
            {
                WoWPlayer player = target as WoWPlayer;
                if ((player != null) && ((player == Me) || player.IsInMyPartyOrRaid))
                {
                    return true;
                }
            }
            else
            {
                WoWPlayer createdByUnit = target.CreatedByUnit as WoWPlayer;
                if ((createdByUnit != null) && ((createdByUnit == Me) || createdByUnit.IsInMyPartyOrRaid))
                {
                    return true;
                }
            }
            return false;
        }

        private static bool IsEnemy(WoWUnit target)
        {
            if (UnitHasAura("Reshape Life", target) || UnitHasAura("Convert", target))
            {
                return true;
            }
            if (IsMyPartyRaidMember(target))
            {
                return false;
            }
            return ((Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground) || (((!target.IsFriendly && target.Attackable) && !target.IsQuestGiver) || ((Me.Combat && IsDummy(target)) && Me.IsFacing(target))));
        }

        #endregion

        #region IsMoving

        private static bool IsMoving(WoWUnit target)
        {
            if ((!target.MovementInfo.MovingBackward && !target.MovementInfo.MovingForward) && !target.MovementInfo.MovingStrafeLeft)
            {
                return target.MovementInfo.MovingStrafeRight;
            }
            return true;
        }

        #endregion

        #region IsMeorFocus

        //private  bool IsMeorFocus(WoWUnit target)
        //{
        //    if (target == Me ||
        //        target == Me.FocusedUnit && ValidUnit(Me.FocusedUnit) && !IsEnemy(Me.FocusedUnit) ||
        //        target == Me.CurrentTarget && ValidUnit(Me.CurrentTarget) && !IsEnemy(Me.CurrentTarget) ||
        //        InArena)
        //    {
        //        return true;
        //    }
        //    return false;
        //}

        #endregion

        #region IsTank

        private static bool IsTank(WoWUnit target)
        {
            return (((target.Entry == 0x11a1a) || UnitHasAura("Vengeance", target)) || (from unit in GroupMembers
                                                                                        where unit.ToPlayer() == target
                                                                                        select unit).Any<WoWPartyMember>(unit => ((unit.Role & WoWPartyMember.GroupRole.Tank) != WoWPartyMember.GroupRole.None)));
        }

        #endregion

        #region NeedHealUnit
        private static bool NeedHealUnit(WoWUnit target)
        {
            return (NeedHealUnitHS.Contains(target.Entry) && target.IsFriendly);
        }
        #endregion

        #region LogTest

        //private static Composite LogTest(string message)
        //{
        //    return new Action(delegate
        //                          {
        //                              Logging.Write(LogLevel.Diagnostic, "LogTest: " + message);
        //                              return RunStatus.Failure;
        //                          });
        //}

        #endregion

        #region UnitAuraTimeLeft

        //private static double UnitAuraTimeLeft(string auraName, WoWUnit u)
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == u.Guid);

        //        if (aura == null)
        //        {
        //            return 0;
        //        }
        //        return aura.TimeLeft.TotalMilliseconds;
        //    }
        //}

        //private static double UnitAuraTimeLeft(int auraID, WoWUnit u)
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null)
        //            return 0;

        //        WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == u.Guid);

        //        if (aura == null)
        //        {
        //            return 0;
        //        }
        //        return aura.TimeLeft.TotalMilliseconds;
        //    }
        //}

        #endregion

        #region ReturningFlag

        //private static DateTime SearchFlagTime;
        //private static void ReturningFlag()
        //{
        //    if (SearchFlagTime >= DateTime.Now)
        //    {
        //        WoWGameObject obj2 = ObjectManager.GetObjectsOfType<WoWGameObject>().FirstOrDefault<WoWGameObject>(delegate(WoWGameObject obj)
        //        {
        //            if (!(obj.Name == "Alliance Flag") && !(obj.Name == "Horde Flag"))
        //            {
        //                return false;
        //            }
        //            return obj.Distance <= 15.0;
        //        });
        //        if (obj2 != null)
        //        {
        //            if (!IsOverrideModeOn)
        //            {
        //                Navigator.MoveTo(obj2.Location);
        //            }
        //            Me.SetFacing(obj2.Location);
        //            obj2.Interact();
        //            Logging.Write("Trying to Return/Pick Up Dropped flag!");
        //        }
        //    }
        //}
        #endregion

        #region SafelyFacingTarget

        private static void SafelyFacingTarget(WoWUnit target)
        {
            if ((!IsUsingAFKBot || !IsMoving(Me)) && ((THSettings.Instance.AutoFace && !IsOverrideModeOn) && !Me.IsSafelyFacing(target)))
            {
                Me.SetFacing(target.Location);
                WoWMovement.ConstantFace(target.Guid);
            }
        }

        #endregion

        #region SetAutoAttack

        private static DateTime SetAutoAttackLast;

        private static Composite SetAutoAttack()
        {
            return new Action(delegate
            {
                if (((Me.CurrentTarget != null) && (SetAutoAttackLast < DateTime.Now)) && !CurrentTargetAttackable(50.0, false, false))
                {
                    Lua.DoString("RunMacroText('/stopattack');", "WoW.lua");
                    SetAutoAttackLast = DateTime.Now + TimeSpan.FromMilliseconds(2000.0);
                    return RunStatus.Failure;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region SpellType

        private readonly HashSet<string> AttackSpells = new HashSet<string> { 
            "Avenger's Shield", "Avenging Wrath", "Crusader Strike", "Consecration", "Divine Storm", "Exorcism", "Hammer of Justice", "Fist of Justice", "Hammer of the Righteous", "Hammer of Wrath", "Holy Wrath", "Inquisition", "Judgment", "Reckoning", "Righteous Fury", "Templar's Verdict", 
            "Turn Evil"
         };

        private readonly HashSet<string> DefendSpells = new HashSet<string> { "[Ardent Defender", "Cleanse", "Devotion Aura", "Divine Protection", "Divine Shield", "Emancipate", "Flash of Light", "Hand of Freedom", "Hand of Protection", "Hand of Sacrifice", "Hand of Salvation", "Holy Radiance", "Lay on Hands", "Redemption", "Sacred Shield" };


        private readonly HashSet<string> SpecialSpells = new HashSet<string> { "Guardian of Ancient Kings", "Holy Avenger", "Holy Prism", "Rebuke" };

        private static readonly HashSet<uint> NeedHealUnitHS = new HashSet<uint> 
        { 
            0xf3ea, 0x116ec, 0x115fe, 0x115fd, 0x116bd, 0x11a1a, 0x11a1b, 0x11a1d, 0x11a1c, 0x11894, 0x117b4, 0x117b4, 0x1193b, 0x1193c, 0x11738 
        };
        
        #endregion

        #region TalentSort

        private static byte TalentSort(WoWUnit target)
        {
            if ((target != null) && target.IsValid)
            {
                switch (target.Class)
                {
                    case WoWClass.Warrior:
                        return 1;

                    case WoWClass.Paladin:
                        if (target.MaxMana <= (target.MaxHealth / 2))
                        {
                            return 1;
                        }
                        return 4;

                    case WoWClass.Hunter:
                        return 2;

                    case WoWClass.Rogue:
                        return 1;

                    case WoWClass.Priest:
                        if (!UnitHasAura(0x1c0c4, target))
                        {
                            return 4;
                        }
                        return 3;

                    case WoWClass.DeathKnight:
                        return 1;

                    case WoWClass.Shaman:
                        if (target.MaxMana >= (target.MaxHealth / 2))
                        {
                            if (UnitHasAura(0x3f55, target))
                            {
                                return 4;
                            }
                            return 3;
                        }
                        return 1;

                    case WoWClass.Mage:
                        return 3;

                    case WoWClass.Warlock:
                        return 3;

                    case WoWClass.Monk:
                        if (!UnitHasAura(0x1c17e, target))
                        {
                            return 1;
                        }
                        return 4;

                    case WoWClass.Druid:
                        if (target.MaxMana >= (target.MaxHealth / 2))
                        {
                            if (UnitHasAura(0x1a0ef, target))
                            {
                                return 4;
                            }
                            return 3;
                        }
                        return 1;
                }
            }
            return 0;
        }

        private static byte TalentSortSimple(WoWUnit target)
        {
            byte num = TalentSort(target);
            if (num == 4)
            {
                return 4;
            }
            if ((num < 4) && (num > 0))
            {
                return 1;
            }
            return 0;
        }

        private static string TalentSortRole(WoWUnit target)
        {
            switch (TalentSort(target))
            {
                case 1:
                    return "Melee";

                case 2:
                    return "Range DPS";

                case 3:
                    return "Range DPS";

                case 4:
                    return "Healer";
            }
            return "Unknow";
        }

        #endregion

        #region TalentValue

        private static bool TalentValue(bool blood, bool frost, bool unholy)
        {
            if (GetCurrentSpec() == "Blood")
            {
                return blood;
            }
            if (!(GetCurrentSpec() == "Unholy"))
            {
                return frost;
            }
            return unholy;
        }

        private static int TalentValue(int blood, int frost, int unholy)
        {
            if (GetCurrentSpec() == "Blood")
            {
                return blood;
            }
            if (!(GetCurrentSpec() == "Unholy"))
            {
                return frost;
            }
            return unholy;
        }

        #endregion

        #region UpdateStatusEvent

        private static void UpdateStatusEvent(object sender, LuaEventArgs args)
        {
            THSettings.Instance.UpdateStatus = true;
        }

        #endregion

        #region OnBotStartedEvent

        private static void OnBotStartedEvent(object o)
        {
            if (Me.Inventory.Equipped.Hands != null)
            {
                Me.Inventory.Equipped.Hands.Name.Contains("Malevolent Gladiator's Scaled Gauntlets");
            }
            Logging.Write("----------------------------------");
            Logging.Write("Update Status on Bot Start");
            Logging.Write("----------------------------------");
            THSettings.Instance.Pause = false;
            THSettings.Instance.UpdateStatus = true;
        }

        #endregion

        #region SpecialUnit

        //private static readonly HashSet<uint> SpecialUnit = new HashSet<uint>
        //    {
        //        60491, //Sha of Anger
        //        62346, //Galleon
        //        60410, //Elegon
        //        60776, //Empyreal Focus
        //        60793, //Celestial Protector
        //        60913, //Energy Charge
        //        60143, //garajal-the-spiritbinder
        //        60412, //Empyreal Focus
        //        63667, //garalon
        //    };

        #endregion

        #region UpdateEventHandler

        private static void UpdateEventHandler()
        {
            if (((IsUsingAFKBot && !InArena) && (!InBattleground && !InDungeon)) && (!InRaid && !EventHandlers.CombatLogAttached))
            {
                EventHandlers.AttachCombatLogEvent();
            }
            if (((!IsUsingAFKBot || InArena) || ((InBattleground || InDungeon) || InRaid)) && EventHandlers.CombatLogAttached)
            {
                EventHandlers.DetachCombatLogEvent();
            }
        }

        #endregion

        #region UpdateCurrentMap

        //public string CurrentMap;

        //private static void UpdateCurrentMapEvent(BotEvents.Player.MapChangedEventArgs args)
        //{
        //    THSettings.Instance.UpdateStatus = true;
        //}

        //private static void UpdateCurrentMap()
        //{
        //    if (InArena)
        //    {
        //        CurrentMap = "Arena";
        //    }
        //    else if (InBattleground && Me.IsFFAPvPFlagged)
        //    {
        //        CurrentMap = "Rated Battleground";
        //    }
        //    else if (InBattleground)
        //    {
        //        CurrentMap = "Battleground";
        //    }
        //    else if (InDungeon)
        //    {
        //        CurrentMap = "Dungeon";
        //    }
        //    else if (InRaid)
        //    {
        //        CurrentMap = "Raid";
        //    }
        //    else
        //    {
        //        CurrentMap = "World";
        //    }

        //    Logging.Write("----------------------------------");
        //    Logging.Write("CurrentMap: " + CurrentMap);
        //    Logging.Write("----------------------------------");
        //}

        #endregion

        #region UpdateMyLatency

        private static double MyLatency;

        private static void UpdateMyLatency()
        {
            MyLatency = StyxWoW.WoWClient.Latency;
            if (MyLatency > 400.0)
            {
                MyLatency = 400.0;
            }
        }

        #endregion

        #region UpdateMyTalent

        private static string _hasTalent = "";

        private static void UpdateMyTalentEvent(object sender, LuaEventArgs args)
        {
            UpdateMyTalent();
        }

        private static void UpdateMyTalent()
        {
            _hasTalent = "";
            for (int i = 1; i <= 0x12; i++)
            {
                _hasTalent = _hasTalent + Lua.GetReturnVal<string>(string.Format("local t= select(5,GetTalentInfo({0})) if t == true then return '['..select(1,GetTalentInfo({0}))..'] ' end return nil", i), 0);
            }
            Logging.Write("----------------------------------");
            Logging.Write("Talent:");
            Logging.Write(_hasTalent);
            Logging.Write("----------------------------------");
            _hasTalent = "";
        }

        #endregion

        #region UpdateRaidPartyMembers

        private static IEnumerable<WoWPartyMember> GroupMembers
        {
            get
            {
                if (Me.GroupInfo.IsInRaid)
                {
                    return Me.GroupInfo.RaidMembers;
                }
                return Me.GroupInfo.PartyMembers;
            }
        }

        //private static void UpdateRaidPartyMembersEvent(object sender, LuaEventArgs args)
        //{
        //    UpdateRaidPartyMembers();
        //}

        //private static DateTime UpdateRaidPartyMembersLast;

        //private static Composite UpdateRaidPartyMembersComp()
        //{
        //    return new Decorator(
        //        ret =>
        //        UpdateRaidPartyMembersLast + TimeSpan.FromSeconds(60) < DateTime.Now ||
        //        UpdateRaidPartyMembersLast + TimeSpan.FromSeconds(10) < DateTime.Now &&
        //        !Me.Combat ||
        //        HasAuraArenaPreparation ||
        //        HasAuraPreparation,
        //        new Action(delegate
        //            {
        //                UpdateRaidPartyMembers();
        //                UpdateRaidPartyMembersLast = DateTime.Now;
        //                return RunStatus.Failure;
        //            }));
        //}

        //private static readonly List<WoWPlayer> RaidPartyMembers = new List<WoWPlayer>();

        //private static void UpdateRaidPartyMembers()
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        EnemyListCache.Clear();
        //        RaidPartyMembers.Clear();

        //        foreach (var woWPartyMember in GroupMembers)
        //        {
        //            if (woWPartyMember.ToPlayer() != null)
        //            {
        //                //Logging.Write("Add " + woWPartyMember.ToPlayer().Class + " to RaidPartyMembers");
        //                RaidPartyMembers.Add(woWPartyMember.ToPlayer());
        //            }
        //        }

        //        if (!RaidPartyMembers.Contains(Me))
        //        {
        //            RaidPartyMembers.Add(Me);
        //        }
        //    }
        //}

        #endregion

        #region UseHealthstone

        private static Composite UseHealthstone()
        {
            return new Decorator(ret => ((THSettings.Instance.HealthStone && Me.Combat) && ((HealWeight(Me) < THSettings.Instance.HealthStoneHP) && (Me.CurrentTarget != null))) && (Me.CurrentTarget.CurrentHealth > HealWeight(Me)), new Styx.TreeSharp.Action(delegate(object param0)
            {
                WoWItem item = Me.BagItems.FirstOrDefault<WoWItem>(o => o.Entry == 0x1588);
                if ((item != null) && (item.CooldownTimeLeft.TotalMilliseconds <= MyLatency))
                {
                    item.Use();
                    Logging.Write("Use Healthstone at " + HealWeight(Me) + "%");
                }
                return RunStatus.Failure;
            }));
        }

        #endregion

        #region UpdateMyNoGCDSpell

        private static readonly HashSet<string> NoGCDSpells = new HashSet<string>();

        private static void UpdateMyNoGCDSpell()
        {
            if (SpellManager.HasSpell("Anti-Magic Shell"))
            {
                NoGCDSpells.Add("Anti-Magic Shell");
            }
            if (SpellManager.HasSpell("Blood Tap"))
            {
                NoGCDSpells.Add("Blood Tap");
            }
            if (SpellManager.HasSpell("Dancing Rune Weapon"))
            {
                NoGCDSpells.Add("Dancing Rune Weapon");
            }
            if (SpellManager.HasSpell("Dark Command"))
            {
                NoGCDSpells.Add("Dark Command");
            }
            if (SpellManager.HasSpell("Dark Simulacrum"))
            {
                NoGCDSpells.Add("Dark Simulacrum");
            }
            if (SpellManager.HasSpell("Death Pact"))
            {
                NoGCDSpells.Add("Death Pact");
            }
            if (SpellManager.HasSpell("Empower Rune Weapon"))
            {
                NoGCDSpells.Add("Empower Rune Weapon");
            }
            if (SpellManager.HasSpell("Icebound Fortitude"))
            {
                NoGCDSpells.Add("Icebound Fortitude");
            }
            if (SpellManager.HasSpell("Lichborne"))
            {
                NoGCDSpells.Add("Lichborne");
            }
            if (SpellManager.HasSpell("Mind Freeze"))
            {
                NoGCDSpells.Add("Mind Freeze");
            }
            if (SpellManager.HasSpell("Rune Tap"))
            {
                NoGCDSpells.Add("Rune Tap");
            }
            if (SpellManager.HasSpell("Vampiric Blood"))
            {
                NoGCDSpells.Add("Vampiric Blood");
            }
            Logging.Write("----------------------------------");
            Logging.Write("Spells that don't use Global Cooldown:");
            foreach (string str in NoGCDSpells)
            {
                Logging.Write(" -" + str);
            }
            Logging.Write("----------------------------------");
        }

        #endregion

        #region UpdateMyGlyph

        private static void UpdateMyGlyphEvent(object sender, LuaEventArgs args)
        {
            UpdateMyGlyph();
        }

        //private static readonly HashSet<string> NoGCDSpells = new HashSet<string> { };
        private static string HasGlyph;
        private static string HasGlyphName;
        private static int GlyphprivateofPestilenceBonus = 0;

        private static void UpdateMyGlyph()
        {
            HasGlyph = "";
            HasGlyphName = "";
            int returnVal = Lua.GetReturnVal<int>("return GetNumGlyphSockets()", 0);
            if (returnVal != 0)
            {
                for (int i = 1; i <= returnVal; i++)
                {
                    int id = Lua.GetReturnVal<int>(string.Format("local enabled, glyphType, glyphTooltipIndex, glyphSpellID, icon = GetGlyphSocketInfo({0});if (enabled) then return glyphSpellID else return 0 end", i), 0);
                    try
                    {
                        if (id > 0)
                        {
                            HasGlyphName = string.Concat(new object[] { HasGlyphName, "[", WoWSpell.FromId(id), " - ", id, "] " });
                            HasGlyph = string.Concat(new object[] { HasGlyph, "[", id, "] " });
                        }
                        else
                        {
                            Logging.Write("Glyphdetection - No Glyph in slot " + i);
                        }
                    }
                    catch (Exception exception)
                    {
                        Logging.Write("We couldn't detect your Glyphs");
                        Logging.Write("Report this message to us: " + exception);
                    }
                }
            }
            Logging.Write("----------------------------------");
            Logging.Write("Glyph:");
            Logging.Write(HasGlyphName);
            Logging.Write("----------------------------------");
            if (HasGlyph.Contains("58657"))
            {
                GlyphprivateofPestilenceBonus = 5;
            }
        }

        #endregion

        #region UpdateStatus

        //private static string UseRotation;
        private static string CurrentBotBase;
        internal static int UseSpecialization;
        private static bool IsUsingAFKBot;
        private static ulong MeGuid;
        private static double MeMaxHealth;

        private static void UpdateStatus()
        {
            if (THSettings.Instance.UpdateStatus && Me.IsValid)
            {
                CurrentBotBase = TreeRoot.Current.Name;
                BurstLast = DateTime.Now;
                Logging.Write("----------------------------------");
                Logging.Write("Building Rotation base on current Talents and Glyphs......");
                Logging.Write("----------------------------------");
                Logging.Write("");
                UpdateEventHandler();
                UpdateMyTalent();
                UpdateMyGlyph();
                PetSpellsUpdate();
                if (Me.Specialization == WoWSpec.DeathKnightBlood)
                {
                    UseSpecialization = 1;
                }
                else if (Me.Specialization == WoWSpec.DeathKnightFrost)
                {
                    UseSpecialization = 2;
                }
                else
                {
                    UseSpecialization = 3;
                }
                Logging.Write("----------------------------------");
                Logging.Write("Hold 1 second Control + " + IndexToKeys(THSettings.Instance.PauseKey) + " To Toggle Pause Mode.");
                Logging.Write("----------------------------------");
                Logging.Write("");
                if ((((TreeRoot.Current.Name == "Questing") || (TreeRoot.Current.Name == "[BETA] Grindbuddy")) || ((TreeRoot.Current.Name == "ArcheologyBuddy") || (TreeRoot.Current.Name == "Auto Angler"))) || (((TreeRoot.Current.Name == "Gatherbuddy2") || (TreeRoot.Current.Name == "Grind Bot")) || (((TreeRoot.Current.Name == "BGBuddy") || (TreeRoot.Current.Name == "DungeonBuddy")) || (TreeRoot.Current.Name == "Mixed Mode"))))
                {
                    IsUsingAFKBot = true;
                }
                else
                {
                    IsUsingAFKBot = false;
                }
                MeGuid = Me.Guid;
                MeMaxHealth = Me.MaxHealth;
                if (THSettings.Instance.BurstKey > 7)
                {
                    Logging.Write("----------------------------------");
                    Logging.Write("Hold 1 second + " + IndexToKeys(THSettings.Instance.BurstKey - 7) + " To Toggle Burst Mode");
                    Logging.Write("----------------------------------");
                    Logging.Write("");
                }
                Logging.Write("----------------------------------");
                Logging.Write("Building Rotation Completed");
                Logging.Write("----------------------------------");
                Logging.Write("");
                Logging.Write("Make sure you always have lastest version with Improved logic and Bug fix");
                Logging.Write("To Update the lastest version, just");
                Logging.Write("Right Click Folder TuanHADKSpecialEdition > SVN Update");
                Logging.Write("----------------------------------");
                THSettings.Instance.UpdateStatus = false;
            }
        }

        #endregion

        #region DebugTime

        private static Composite SWStart()
        {
            return new Action(delegate
            {
                sw.Reset();
                sw.Start();
                return RunStatus.Failure;
            });
        }

        private static Composite SWStop(string FunctionName)
        {
            return new Action(delegate
            {
                sw.Stop();
                Logging.Write(LogLevel.Diagnostic, "{0} ms - {1} ",
                              Math.Round(sw.Elapsed.TotalMilliseconds, 5), FunctionName);
                sw.Reset();
                return RunStatus.Failure;
            });
        }

        private static bool Eval(string Name, System.Func<bool> func)
        {
            sw.Reset();
            sw.Start();
            bool result = func();
            sw.Stop();
            Logging.Write(LogLevel.Diagnostic, "{0} ms - {1} , result is {2}",
                          Math.Round(sw.Elapsed.TotalMilliseconds, 5), Name,
                          result);
            return result;
        }

        private static int Eval(string Name, System.Func<int> func)
        {
            sw.Reset();
            sw.Start();
            int result = func();
            sw.Stop();
            Logging.Write(LogLevel.Diagnostic, "{0} ms - {1} , result is {2}",
                          Math.Round(sw.Elapsed.TotalMilliseconds, 5), Name,
                          result);
            return result;
        }

        #endregion

        #region ValidUnit

        private static bool ValidUnit(WoWUnit u)
        {
            return ((((u != null) && u.IsValid) && (u.Attackable && u.CanSelect)) && ((u.IsAlive && !u.IsCritter) && !Blacklist.Contains(u.Guid, BlacklistFlags.All)));
        }

        #endregion
    }
}